package com.huangfu.learning.javabase.java.pattern.structure.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created with IntelliJ IDEA.
 * Author: huangfu.daohui
 * Date: 2018/7/21
 * Time: 10:03
 * Version: 1.0
 * Description: 动态代理实现AOP
 **/
public class AopProxy {
    public static void main(String[] args) {
        //创建代理工厂
        AopProxyFactory aopProxyFactory = new AopProxyFactory();

        // 设置目标对象
        aopProxyFactory.setTarget(new ManWaiterImpl());

        //设置前置增强
        aopProxyFactory.setBeforeAdvice(new BeforeAdvice() {
            @Override
            public void before() {
                System.out.println("目标方法的前置增强:您好！。。。before");
            }
        });

        aopProxyFactory.setAfterAdvice(new AfterAdvice() {
            @Override
            public void after() {
                System.out.println("目标方法的后置增强:再见！。。。after");
            }
        });

        //调用目标方法
        WaterInterf water = (WaterInterf) aopProxyFactory.createProxy();
//        water.service("huangfu");
        water.shouqian();
    }
}

//接口  服务员
interface WaterInterf {
    // 服务
    String service(String name);

    void shouqian();
}

// 实现类
class ManWaiterImpl implements WaterInterf {

    @Override
    public String service(String name) {
        return name + " ManWaiterImpl.service 服务员服务成功";
    }

    @Override
    public void shouqian() {
        System.out.println("ManWaiterImpl.shouqian 服务员收钱成功");
    }
}

// 前置增强
interface BeforeAdvice {
    void before();
}

//后置增强
interface AfterAdvice {
    void after();
}


/**
 * Date: 2018/7/21
 * Time: 10:03
 * Description:用来生成代理对象
 * <p>
 * 1.代理工厂
 * 2.给工厂设置三个属性
 * 目标对象setTargetObject
 * 前置增强setBeforeAdvice
 * 后置增强setAfterAdvice
 * 3.调用createProxy得到代理对象
 * 执行过程：
 * BeforeAdvice.before
 * 目标对象的目标方法
 * AfterAdvice.after
 **/
class AopProxyFactory {

    // 目标对象
    private Object target;

    // 前置增强
    private BeforeAdvice beforeAdvice;

    //后置增强
    private AfterAdvice afterAdvice;

    //生成代理对象
    public Object createProxy() {
        // 返回代理对象，三大参数：类加载器、接口、调用处理器
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //调用前置
                if (beforeAdvice != null) {
                    beforeAdvice.before();
                }
                //调用方法
                Object result = method.invoke(target, args);
                //调用后置
                if (afterAdvice != null) {
                    afterAdvice.after();
                }
                //返回结果
                return result;
            }
        });
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public BeforeAdvice getBeforeAdvice() {
        return beforeAdvice;
    }

    public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
        this.beforeAdvice = beforeAdvice;
    }

    public AfterAdvice getAfterAdvice() {
        return afterAdvice;
    }

    public void setAfterAdvice(AfterAdvice afterAdvice) {
        this.afterAdvice = afterAdvice;
    }
}